#include "NetBase.h"
#include <windows.h>
#include <time.h>

#include <iostream>

#define CLIENT

#ifdef LIB_NET_EXPORT
#else
using namespace std;

class CServerNetTest : public CNetBase
{
public:
    CServerNetTest()
        :iReceiveByteCount(0), iReceivePackageCount(0), iTotalSocketCount(0), iOnlineSocketCount(0)
    {

    }
    /**
     * @brief 收到消息事件
     */
    virtual bool OnPacket(const int iSocket, char *pBuff, int iLen)
    {
        if (!CNetBase::OnPacket(iSocket, pBuff, iLen))
        {
            printf("ERROR socket:%d receive buff false\n", iSocket);
            return false;
        }

        //printf("Debug socket:%d receive:%s\n", iSocket, pBuff);
        ++iReceivePackageCount;
        if (iReceivePackageCount % 1000 == 0)
        {
            printf("recv and send:%d socket:%d\n", iReceivePackageCount, iSocket);
        }
        iReceiveByteCount += iLen;

        int iSendLen = Send(iSocket, pBuff, iLen);
        
        if( iSendLen < iLen )
        {
            printf("ERROR socket:%d send not complete\n", iSocket);
            Close(iSocket);
        }

        return true;
    }

    /**
     * @brief 收到连接事件
     */
    virtual bool OnAccept(const int iListenSocket, const int iClientSocket)
    {
        if (!CNetBase::OnAccept(iListenSocket, iClientSocket))
        {
            return false;
        }
        ++iTotalSocketCount;
        ++iOnlineSocketCount;
        printf("DEBUG new socket:%d \n", iClientSocket);
        return true;
    }

    /**
     * @brief 收到关闭事件
     */
    virtual bool OnClose(const int iSocket)
    {
        if (!CNetBase::OnClose(iSocket))
        {
            return false;
        }

        --iOnlineSocketCount;
        printf("DEBUG close socket:%d\n", iSocket);
        return 0;
    }

private:
    int iReceiveByteCount;
    int iReceivePackageCount;
    int iTotalSocketCount;
    int iOnlineSocketCount;
};

#ifdef CLIENT
int main_server()
#else
int main()
#endif
{
    printf("server\n");
    CServerNetTest cServerNet;

    cServerNet.Init();
    cServerNet.AddListen(NULL, 10812);

    while (true)
    {
        int iCount = cServerNet.Polling(1);
        if (0 < iCount)
        {
            Sleep(1);
        }
    }
    return 0;
}


#define MAX_CLIENT_COUNT 60
#define MAX_SEND_COUNT 100

class CClientNetTest : public CNetBase
{
public:
    CClientNetTest()
        :m_bReady(false), m_iSendCount(0), m_iRecvCount(0), m_iSocket(-1)
    {
    }
    /**
     * @brief 收到消息事件
     */
    virtual bool OnPacket(const int iSocket, char *pBuff, int iLen)
    {
        if (!CNetBase::OnPacket(iSocket, pBuff, iLen))
        {
            printf("ERROR socket:%d receive buff false\n", iSocket);
            return false;
        }
        if (m_iRecvCount % 1000 == 0)
        {
            printf("recv count:%d socket:%d\n", m_iRecvCount, m_iSocket);
        }
        ++m_iRecvCount;

        return true;
    }

    /**
     * @brief 收到消息事件
     */
    virtual bool OnConnect(const int iSocket)
    {
        if (!CNetBase::OnConnect(iSocket))
        {
            return false;
        }

        printf("DEBUG connect socket:%d\n", iSocket);
        m_bReady = true;
        m_iSocket = iSocket;
        return true;
    }

    /**
     * @brief 收到关闭事件
     */
    virtual bool OnClose(const int iSocket)
    {
        if (!CNetBase::OnClose(iSocket))
        {
            return false;
        }
        printf("DEBUG close socket:%d\n", iSocket);
        return 0;
    }
    /**
     * @brief 发送报文
     */
    virtual int Send(const int iSocket, const char *pBuff, const int iLen)
    {
        int iSendLen = CNetBase::Send(iSocket, pBuff, iLen);
        if (iSendLen < iLen)
        {
            return iSendLen;
        }
        if (m_iSendCount % 1000 == 0)
        {
            printf("DEBUG send count:%d socket:%d\n", m_iSendCount, iSocket);
        }
        if (m_iSendCount >= MAX_SEND_COUNT)
        {
            printf("DEBUG send finish socket:%d\n", iSocket);
        }
        return iSendLen;
    }
public:
    bool m_bReady;
    int m_iSendCount;
    int m_iRecvCount;
    int m_iSocket;
};
#ifdef CLIENT
int main()
#else
int main_client()
#endif
{
    printf("client\n");
    vector<CClientNetTest*> vecClient;

    string csBuff[MAX_CLIENT_COUNT];

    for (int i = 0; i < MAX_CLIENT_COUNT; ++i)
    {
        CClientNetTest *pClient = new CClientNetTest();
        if (pClient == NULL)
        {
            continue;
        }
        pClient->Init();
        pClient->AddConnect("127.0.0.1", 10812);
        vecClient.push_back(pClient);

        char csTmp[16];
#ifdef _WIN32
        _itoa_s(i + 1, csTmp, 10);
#else
        itoa(i + 1, csTmp, 10);
#endif
        csBuff[i] = "";

        int iLen = (i + 1) * 10;

        for (int j = 0; j < iLen; ++j)
        {
            csBuff[i].append(csTmp);
        }
    }

    int iFinish = 0;
    while (true)
    {
        int iSize = vecClient.size();
        for (int i = 0; i < iSize; ++i)
        {
            CClientNetTest* pClient = vecClient[i];
            if (NULL ==pClient)
            {
                continue;
            }
            
            pClient->Polling(0);

            if (!pClient->m_bReady)
            {
                continue;
            }
            
            if (pClient->m_iSendCount >= MAX_SEND_COUNT)
            {
                if (pClient->m_iRecvCount == pClient->m_iSendCount)
                {
                    ++iFinish;
                    pClient->m_bReady = false;
                    pClient->Close(pClient->m_iSocket);
                }
                continue;
            }
            pClient->Send(pClient->m_iSocket, csBuff[i].c_str(), csBuff[i].length());
            ++pClient->m_iSendCount;
        }
        if (iFinish == MAX_CLIENT_COUNT)
        {
            break;
        }
    }
    system("pause");
    return 0;
}

#include "DataPool.h"

int main_pool()
{
    CDataPool<128> cDataPool128;
    vector<char *> vecCS;

    srand(time(NULL));

    for (int i = 0; i < 10000; ++i)
    {
        int iRand = rand()%10;
        if (iRand > 3)
        {
            char *pCS = cDataPool128.Create();
            if (pCS == NULL)
            {
                continue;
            }
            snprintf(pCS, 128, "hello world");
            vecCS.push_back(pCS);
            printf("add  |%s\n", cDataPool128.PrintString());
        }
        else
        {
            if (vecCS.size() > 0)
            {
                iRand = iRand % vecCS.size();
                char *temp = vecCS[iRand];
                vecCS.erase(vecCS.begin() + iRand);
                cDataPool128.Release(temp);
            }
            printf("remove|%s\n", cDataPool128.PrintString());
        }
    }


    system("pause");

    return 0;
}

#endif